use crate::common::{error::ApiError, types::R2D2Pool};
use log::error;
use redis::Commands;

pub struct RedisUtil;
pub type R2d2PooledCon = r2d2::PooledConnection<redis::Client>;

impl RedisUtil {
    fn get_connection(pool: &R2D2Pool) -> Result<R2d2PooledCon, ApiError> {
        pool.get().map_err(|e| {
            error!("redis connection error: {}", e);
            ApiError::InternalServerError("获取Redis连接失败")
        })
    }

    pub fn set(pool: &R2D2Pool, key: &str, value: &str, ttl: u64) -> Result<(), ApiError> {
        RedisUtil::get_connection(pool)?
            .set_ex(key, value, ttl)
            .map_err(ApiError::from)
    }

    pub fn get(pool: &R2D2Pool, key: &str) -> Result<Option<String>, ApiError> {
        RedisUtil::get_connection(pool)?
            .get(key)
            .map_err(ApiError::from)
    }

    pub fn del(pool: &R2D2Pool, key: &str) -> Result<(), ApiError> {
        RedisUtil::get_connection(pool)?
            .del(key)
            .map_err(ApiError::from)
    }

    pub fn ttl(pool: &R2D2Pool, key: &str) -> Result<i64, ApiError> {
        RedisUtil::get_connection(pool)?
            .ttl(key)
            .map_err(ApiError::from)
    }

    pub fn hset(pool: &R2D2Pool, key: &str, field: &str, value: &str) -> Result<(), ApiError> {
        RedisUtil::get_connection(pool)?
            .hset(key, field, value)
            .map_err(ApiError::from)
    }

    pub fn hget(pool: &R2D2Pool, key: &str, field: &str) -> Result<Option<String>, ApiError> {
        RedisUtil::get_connection(pool)?
            .hget(key, field)
            .map_err(ApiError::from)
    }
}
